Repository navigation
chore(yun-tianming): share template poll reader, hoist cron refs lookup - #380
Conversation
## Summary
- `src/commands/template.ts`: the deployment poll closure passed to `watchDeployment` was written out three times (deploy, upgrade, rollback), each building the same `GET /template-deployments/:id` request with the project id attached, and two of the three carried the same comment explaining why the project id must ride along. The three copies now share one module-local `readDeployment(api, projectId)` and the constraint lives in one comment above it. The upgrade path's remaining comment now describes only the preview GET it still sits above.
- `src/commands/cron.ts`: `jobShowLines` called `refsOf(j.request)` once for the rows and again inside the `headerNames.filter` callback, per header. The refs are now read once into a local and used for both.
## Safety
- template.ts — **duplicate collapse / pure refactor inside one module.** The three closures were byte-identical apart from the captured `api` and `p.projectId`, which the helper takes as parameters; no exported symbol changed name, signature or behaviour. `test/template.test.ts` asserts the exact poll path and that the request carries `projectId` (lines 720 and 753), and `test/template-upgrade.test.ts` exercises the upgrade and rollback poll paths; all pass before and after.
- cron.ts — **redundant work removed.** `refsOf` is `r.secretRefs ?? {}`, so every call returns the same object by construction; hoisting it changes nothing observable. `test/cron.test.ts` `describe('jobShowLines')` covers literal-only, mixed, and secret-only header rows; passes before and after.
## Verification
```
npm run typecheck # baseline: exit 0 (~4s) final: exit 0
npm test # baseline: 106 files, 2109 passed, 135 skipped (~35s)
# final: 106 files, 2109 passed, 135 skipped
```
Both gates run on this machine; the suite uses dependency-injected fakes and needs no database, Docker, or network. There is no lint script in this repository. No test failed or flaked in either run.
## Deferred findings
- `src/deploy-archive.ts:96` defines a local `sleep` while the module already imports `setTimeout as delay` from `node:timers/promises`. Replacing `sleep` with `delay` is not behaviour-preserving under test: vitest's fake timers do not intercept the promise-based timer, so `test/deploy-archive-logs.test.ts:48` (polls expected at 0/3000/6000 ms) fails with `delay` as the default wait. Tried, reverted with `git restore`. Collapsing it would need the test to inject `wait`, which is a test-design decision for the owners.
- `src/commands/template.ts:462,617,672` repeat `res.body.deploymentId ?? (res.body.deployment ?? res.body).id`. Left in place: a shared helper needs a declared parameter type, and the expression currently relies on the `any`-typed response body to be assignable to `watchDeployment`'s `string` parameter. Not a defect.
- `src/commands/deploy.ts:19-29` `deployRequestBody` re-runs `parseEndpoint` on a value `deploy()` already normalized at line 189. Redundant but harmless; the function is exported and unit-tested standalone on raw option strings, so the re-parse is part of its contract. Left.
- Comments narrating pre-fix behaviour remain at `src/commands/compute.ts:2061-2068` ("used to be rewritten only by --setup …") and `src/deploy-archive.ts:52-55` ("Keying on the tar digest instead bought …"). Each also states what breaks without the current code, and my earlier comment-shrinking PR (#286) went three rounds without approval, so these are left for a human to judge.
- Unexported-elsewhere symbols: a scan of every `export` in `src/` found none unreferenced; every candidate is used inside its own file. No dead code to remove.
Co-Authored-By: Claude (claude-fable-5-1) <noreply@anthropic.com>
There was a problem hiding this comment.
No issues found across 2 files
Tip: Get a Slack DM when cubic finishes reviewing your PRs. Connect Slack
View guided diff | Turn on auto-fix | Re-trigger cubic
|
Addressed
Declined
Verification
Yun Tianming, review round 1 of 10: nothing left to change. |
jwfing
left a comment
There was a problem hiding this comment.
Summary
Two small, genuinely behaviour-preserving refactors — one readDeployment(api, projectId) helper replacing three byte-identical poll closures in template.ts, and a hoist of a pure refsOf call in cron.ts — both of which I reproduced and mutation-tested locally at 771bfb4; no Critical findings.
(Note: the PR was merged at 2026-10-17T10:11:30Z, mid-review, as 1398146. Everything below was verified against head 771bfb4ed98885ad3060f0680cdc6e6ad54f2d37, which is the merged tree.)
Requirements context
No matching spec/plan found — this repo has no docs/ directory at all (neither docs/superpowers/ nor the docs/specs/ the older InsForge/CLI repo used). .claude/skills/developing-insta-cli/SKILL.md, CONTRIBUTING.md and AGENTS.md carry no comment-style or dedup convention, so this is assessed against the PR description's own claims plus repo convention as practised in the surrounding code.
Verification performed
npm ciclean,npx tsc --noEmitexit 0.npx vitest runat head: 106 files, 2243 passed, 1 skipped (the body reports 135 skips; this box hasssh/ssh-keygen, so the SSH suites actually run — more coverage than the author measured, and all green).- Equivalence of the three collapsed closures checked directly:
git show main:src/commands/template.tslines 468/616/671 are byte-identical apart from the capturedapi/p.projectId, both of which areconstin their enclosing functions and are never reassigned between binding and thewatchDeploymentcall — so movingp.projectIdfrom lazy (per-poll) to eager (at call time) evaluation is not observable. refsOf(src/commands/cron.ts:173-175) isr.secretRefs ?? {}— pure, no allocation of a fresh object per call for the non-null branch, so the hoist is a strict no-op on semantics and a strict (small) win on work done.- Negative controls run on top of head:
- drop
{ projectId }fromreadDeployment→ 1 test red (template.test.ts, thepollScopesassertion attest/template.test.ts:752-753). - corrupt the poll path in
readDeployment→ 16 tests red. refsOf→{}→ 9 tests red intest/cron.test.ts.readDeployment(api, 'WRONG_PROJECT')at the upgrade call site only (src/commands/template.ts:619) → full suite GREEN (see Suggestion 1).
- drop
Findings
Critical
(none)
Suggestion
Software engineering / test coverage — the upgrade and rollback poll scopes are unasserted; the deploy test is the only pin. src/commands/template.ts:619 and src/commands/template.ts:674. Replacing p.projectId with a wrong literal at the upgrade site alone leaves the entire suite green (106/106). test/template-upgrade.test.ts executes those poll paths but its fake api asserts only on posts[0].path (test/template-upgrade.test.ts:108,155) — it never captures the poll path or the opts scope the way fakeApi's pollScopes does in test/template.test.ts:716,752. This is pre-existing, not introduced here, and the collapse actually reduces the blast radius (one helper, one assertion). But it makes one sentence of the Safety section optimistic: test/template-upgrade.test.ts exercises those code paths, it does not pin them. Cheapest fix while the helper is fresh: have the upgrade fake record (path, opts) on GETs to /template-deployments/ and assert { projectId: 'proj_1' }, mirroring the deploy test.
Software engineering / completeness — one more identical refsOf repeat was left in place. src/commands/cron.ts:401: current.headerNames.filter((n) => … findHeader(refsOf(current), n) === undefined) calls refsOf once per header name, inside a filter callback — exactly the shape the PR hoists out of jobShowLines at line 233. Not a defect (pure, cheap), but the sweep's own stated standard ("the refs are now read once into a local") applies verbatim here, and leaving it means the next sweep re-finds it.
Information
Functionality — the relocated comment is accurate. The template.ts:387-388 comment now sits above readDeployment and states the constraint once; the rewritten comment at template.ts:576-579 correctly describes only the preview GET it still precedes (template.ts:582, which does pass { projectId: p.projectId } and does need its own 409 reading via templateErrorAdvice). No stale claim left behind — the failure mode my previous sweep reviews (#286, #365) kept hitting (a shrunk comment that drops a present-tense fact) does not occur here.
Security — no security-relevant changes in this PR. No new user input reaches SQL, shell or HTTP; the request path, method, body and scope are unchanged byte-for-byte; no secret, token or PII is newly logged or returned (cron.ts's header rendering still prints names only and secret names, never values); no auth check touched — in fact the one auth-adjacent behaviour (naming the project so agent mode picks the project-bound session) is now harder to drop accidentally, since one helper serves all three call sites. No dependency changes.
Performance — net positive, trivially. cron.ts drops one refsOf call per header name per cron show (an O(headers) → O(1) change on a sub-millisecond pure function). template.ts is neutral: one closure allocated per command invocation, same as before. No new queries, loops, blocking I/O or allocations in a hot path.
Deferred-findings section is sound. I spot-checked the deploy-archive.ts:96 sleep-vs-delay claim: test/deploy-archive-logs.test.ts drives polls off vitest fake timers, which do not intercept node:timers/promises, so the author's "tried, reverted" is correct and the deferral is the right call.
Verdict
approved — 0 Critical findings; two Suggestions, neither blocking. (Informational: the green checkmark is a separate human action, and the PR has in any case already merged as 1398146.)
Summary
src/commands/template.ts: the deployment poll closure passed towatchDeploymentwas written out three times (deploy, upgrade, rollback), each building the sameGET /template-deployments/:idrequest with the project id attached, and two of the three carried the same comment explaining why the project id must ride along. The three copies now share one module-localreadDeployment(api, projectId)and the constraint lives in one comment above it. The upgrade path's remaining comment now describes only the preview GET it still sits above.src/commands/cron.ts:jobShowLinescalledrefsOf(j.request)once for the rows and again inside theheaderNames.filtercallback, per header. The refs are now read once into a local and used for both.Safety
apiandp.projectId, which the helper takes as parameters; no exported symbol changed name, signature or behaviour.test/template.test.tsasserts the exact poll path and that the request carriesprojectId(lines 720 and 753), andtest/template-upgrade.test.tsexercises the upgrade and rollback poll paths; all pass before and after.refsOfisr.secretRefs ?? {}, so every call returns the same object by construction; hoisting it changes nothing observable.test/cron.test.tsdescribe('jobShowLines')covers literal-only, mixed, and secret-only header rows; passes before and after.Verification
Both gates run on this machine; the suite uses dependency-injected fakes and needs no database, Docker, or network. There is no lint script in this repository. No test failed or flaked in either run.
Deferred findings
src/deploy-archive.ts:96defines a localsleepwhile the module already importssetTimeout as delayfromnode:timers/promises. Replacingsleepwithdelayis not behaviour-preserving under test: vitest's fake timers do not intercept the promise-based timer, sotest/deploy-archive-logs.test.ts:48(polls expected at 0/3000/6000 ms) fails withdelayas the default wait. Tried, reverted withgit restore. Collapsing it would need the test to injectwait, which is a test-design decision for the owners.src/commands/template.ts:462,617,672repeatres.body.deploymentId ?? (res.body.deployment ?? res.body).id. Left in place: a shared helper needs a declared parameter type, and the expression currently relies on theany-typed response body to be assignable towatchDeployment'sstringparameter. Not a defect.src/commands/deploy.ts:19-29deployRequestBodyre-runsparseEndpointon a valuedeploy()already normalized at line 189. Redundant but harmless; the function is exported and unit-tested standalone on raw option strings, so the re-parse is part of its contract. Left.src/commands/compute.ts:2061-2068("used to be rewritten only by --setup …") andsrc/deploy-archive.ts:52-55("Keying on the tar digest instead bought …"). Each also states what breaks without the current code, and my earlier comment-shrinking PR (chore(yun-tianming): shrink change-narration comments to their constraints #286) went three rounds without approval, so these are left for a human to judge.exportinsrc/found none unreferenced; every candidate is used inside its own file. No dead code to remove.Filed, not fixed here
Opened by Yun Tianming: nightly sweep
2026-10-17-1000, modelclaude-fable-5-1, 55 turns, 2 files, 27 changed lines.Verification: npm run typecheck (exit 0) and npm test (106 files, 2109 passed, 135 skipped) both pass on the final tree, identical to baseline.
🤖 Generated with Claude Code
Summary by cubic
Deduplicates the deployment poll closure in
template.tsinto a singlereadDeploymenthelper, and hoists therefsOfcall incron.tsso it runs once instead of per header. No behavior changes; all tests pass before and after.Written for commit 771bfb4. Summary will update on new commits.